#include "noisegateucs.h"
#include "dm/dmdef.h"

NoiseGateUCS::NoiseGateUCS(QWidget *parent)
    : AWidget{parent}
{
    setFixedSize(330, 330);

    m_threshold = NOISE_GATE_THRESHOLD_DEFAULT;

    setMouseTracking(true);
    setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
}

void NoiseGateUCS::setThreshold(const int &threshold)
{
    if (m_threshold != threshold) {
        m_threshold = std::clamp(threshold, NOISE_GATE_THRESHOLD_MIN, NOISE_GATE_THRESHOLD_MAX);
        update();
    }
}

void NoiseGateUCS::paintEvent(QPaintEvent *event)
{
    QWidget::paintEvent(event);

    const double labelWidth = 30 * ratio();

    m_rectThreshold = QRectF(0, 0, 15 * ratio(), 15 * ratio());
    m_rectRatio = QRectF(0, 0, 15 * ratio(), 15 * ratio());

    QStyleOption opt;
    opt.initFrom(this);
    QPainter painter(this);
    style()->drawPrimitive(QStyle::PE_Widget, &opt, &painter, this);
    painter.setRenderHint(QPainter::Antialiasing, true);
    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);

    auto pen = painter.pen();
    pen.setWidth(1);
    pen.setColor(QColor(115, 119, 128));
    painter.setPen(pen);

    // 坐标系实际大小
    const auto aw = width() - 1.5 * labelWidth;
    const auto ah = height() - 1.5 * labelWidth;

    m_cRect = QRectF(labelWidth, labelWidth / 2, aw, ah);

    const auto ox = m_cRect.bottomLeft().x();
    const auto oy = m_cRect.bottomLeft().y();

    painter.drawRect(m_cRect);

    // 网格
    for (int gain = NOISE_GATE_THRESHOLD_MIN; gain <= NOISE_GATE_THRESHOLD_MAX; gain += 10) {
        auto x = ox + aw * (gain - NOISE_GATE_THRESHOLD_MIN) / NOISE_GATE_THRESHOLD_LENGTH;
        auto y = oy - ah * (gain - NOISE_GATE_THRESHOLD_MIN) / NOISE_GATE_THRESHOLD_LENGTH;

        painter.drawLine(QPointF(x, m_cRect.topLeft().y()), QPointF(x, oy));
        painter.drawLine(QPointF(ox, y), QPointF(m_cRect.bottomRight().x(), y));

        painter.drawText(QRectF(ox - labelWidth, y - labelWidth / 2, labelWidth - 5 * ratio(), labelWidth), Qt::AlignVCenter | Qt::AlignRight, QString::number(gain));
        painter.drawText(QRectF(x - labelWidth / 2, oy + 5 * ratio(), labelWidth, labelWidth), Qt::AlignHCenter, QString::number(gain));
    }

    m_rectThreshold.moveCenter(QPointF(ox + aw * (m_threshold - NOISE_GATE_THRESHOLD_MIN) / NOISE_GATE_THRESHOLD_LENGTH,
                                       oy - ah * (m_threshold - NOISE_GATE_THRESHOLD_MIN) / NOISE_GATE_THRESHOLD_LENGTH));

    painter.setPen(Qt::NoPen);
    painter.setBrush(QColor(119, 192, 51, 48));

    const QPointF points[4] = {
        QPointF(m_rectThreshold.center().x(), oy),
        m_rectThreshold.center(),
        m_cRect.topRight(),
        m_cRect.bottomRight()
    };
    painter.drawConvexPolygon(points, 4);


    pen.setStyle(Qt::DashLine);
    pen.setColor(QColor(119, 192, 51));
    painter.setPen(pen);
    painter.drawLine(QPointF(m_cRect.topLeft().x(), points[1].y()), QPointF(m_cRect.topRight().x(), points[1].y()));
    painter.drawLine(QPointF(points[1].x(), m_cRect.topLeft().y()), QPointF(points[1].x(), m_cRect.bottomLeft().y()));

    pen.setWidth(2);
    pen.setStyle(Qt::SolidLine);
    painter.setPen(pen);
    painter.drawLine(points[0], points[1]);
    painter.drawLine(points[1], points[2]);

    painter.setPen(Qt::white);
    painter.setBrush(Qt::white);

    painter.drawEllipse(m_rectThreshold);
}

void NoiseGateUCS::mousePressEvent(QMouseEvent *event)
{
    if (event->button() == Qt::LeftButton) {
        m_selected = m_rectThreshold.contains(event->pos());
    }
    QWidget::mousePressEvent(event);
}

void NoiseGateUCS::mouseMoveEvent(QMouseEvent *event)
{
    if (m_rectThreshold.contains(event->pos())) {
        setCursor(Qt::SizeBDiagCursor);
    }
    if (m_selected) {
        emit thresholdChanged(toThreshold(event->pos()));
    }
}

void NoiseGateUCS::mouseReleaseEvent(QMouseEvent *event)
{
    if (m_selected && event->button() == Qt::LeftButton) {
        m_selected = false;
    }

    QWidget::mouseReleaseEvent(event);
}

int NoiseGateUCS::toThreshold(const QPointF &point) const
{
    return NOISE_GATE_THRESHOLD_MAX - NOISE_GATE_THRESHOLD_LENGTH * (point.y() - m_cRect.topLeft().y()) / (m_cRect.bottomLeft().y() - m_cRect.topLeft().y());
}
